using System;
using System.Threading;
using System.IO;
using System.Collections;
 
public class HelloWorld
{
	
	class Node{
		string name;
		ArrayList children = new ArrayList();
		public Node (string name)
		{
			this.name = name;
		}
		public void add(Object child){
			children.Add(child);
		}
		public string Name {
			get {
				return this.name;
			}
		}

		public ArrayList Children {
			get {
				return this.children;
			}
		}

	}
	
	class NodeWriter{
		TextWriter w;
		
		public NodeWriter (TextWriter w)
		{
			this.w = w;
		}

		
		public void write(Object nodeOrAtom){
			if( nodeOrAtom is Node ){
				write( (Node)nodeOrAtom );
			}else{
				w.Write(nodeOrAtom);
			}
		}
		public void write(Node n){
			w.Write ("("+n.Name);
			foreach(Object c in n.Children){
				w.Write(" ");
				write(c);
			}
			w.Write (")");
		}
	}
	
	static public void Main(){

		StreamReader streamReader = new StreamReader("../../state.txt");
		string text = streamReader.ReadToEnd();
		streamReader.Close();
		Node parseRes = (Node)parse (text);
		Console.WriteLine("parseRes: "+parseRes);
		new NodeWriter(Console.Out).write(parseRes);
		Console.Out.WriteLine();
		Console.WriteLine("finished: "+text);
	}

   static Object parse(string text){
		int idx=0;
		return parse (text, ref idx);
	}

	static Object parse(string text, ref int i){
		skipSpace(text, ref i);
		if( text[i]=='(' ){
			return parseGroup(text, ref i);
		}else{
			string atom = parseAtom(text, ref i);
			Console.WriteLine("atom "+atom);
			return atom;
		}
	}
	
	static void skipSpace(string text, ref int pos){
		while(pos < text.Length && spaceChar(text[pos])){
			pos++;
		}
	}

	static Object parseGroup(string text, ref int idx){
		if( text[idx]!='(' ){
			throw new Exception("not ( char at "+idx+" in "+text);
		}
		idx++;
		Console.WriteLine("group start");
		string groupName = (string)parse(text, ref idx);
		Node res = new Node(groupName);
		for(;;){
			Console.WriteLine("group remaining "+text.Substring(idx));
			Object o = parse (text, ref idx);
			res.add(o);
			skipSpace(text, ref idx);
			if( text[idx]==')' ){
				idx++;
				break;
			}
		}
		Console.WriteLine("group end");
		return res;
	}

	static string parseAtom(string text, ref int idx){
		if( !atomChar(text[idx]) ){
			throw new Exception("non-atom char at "+idx+" in "+text);
		}
		int end=idx;
		for( int i=idx; i<text.Length; i++ ){
			if( !atomChar(text[i]) ){
				end=i;
				break;
			}
		}
		string ret = text.Substring(idx, end-idx);
		idx = end;
		return ret;
	}
	
			
	static bool spaceChar(char c){
			return c==' ' || c=='\t' || c=='\n';
	}
	
	static bool atomChar(char c){
		return !spaceChar(c) && c!='(' && c!=')';
	}
	
 
}

